package view;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.border.BevelBorder;

import model.LevelPack;

import java.io.*;

/**
 * LevelPackFrame is used to display all the levels currently loaded on the user's
 * system, and to allow the user to select individual levels and create level packs.
 * 
 * @author Alexander Craig
 */
@SuppressWarnings("serial")
public class LevelPackFrame extends JFrame {

	private static final String ERROR_EXPORTING_MSG = "Error exporting file.";
	private static final String LEVEL_PACK_FILE_EXISTS_MSG = "Level pack file already exists, please select another name.";
	private static final String LEVEL_PACK_SAVED_SUCCESFULLY_MSG = "Level pack saved succesfully!";
	private static final String SELECT_FILENAME_MSG = "Please select a filename for your level pack (without extension):";
	private static final String ERROR_PANE_HEADER = "Error";
	private static final String NO_LEVELS_SELECTED_MSG = "No levels have been selected to add to the level pack!";
	/** The list of all levels currently loaded on the system */
	private DefaultListModel loadedLevels;
	/** The list of all levels selected to be packaged in a level pack */
	private DefaultListModel packLevels;
	/** The lists used to display the list model data */
	private JList levelList, packList;
	
	/**
	 * Creates a new LevelPackFrame
	 * @param title	the title of the new frame
	 * @param parent	the parent component of this frame, used for positioning
	 */
	public LevelPackFrame(String title, Component parent) {
		super(title);
		loadedLevels = new DefaultListModel();
		packLevels = new DefaultListModel();
		
		initLists();
		initButtons();
		
		// Size, position, and display the frame
		this.pack();
		this.setLocationRelativeTo(parent);
		this.setVisible(true);
	}

	/**
	 * Initialises the list of existing levels and the list of level pack levels.
	 */
	private void initLists() {
		// Initialise the list of existing levels
		levelList = new JList(loadedLevels);
		JScrollPane levelScrollPane = new JScrollPane(levelList);
		levelScrollPane.setPreferredSize(new Dimension(150,200));
		levelScrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED), "Available Levels"));
		this.getContentPane().add(levelScrollPane, BorderLayout.WEST);
		File levelsFolder = new File("levels");
		String[] existingLevels = levelsFolder.list();
		for(int i = 0; i < existingLevels.length; i++) {
			if (existingLevels[i].endsWith(".ots")) {
				loadedLevels.addElement(existingLevels[i]);
			}
		}
		
		
		// Initialise the list of level pack levels
		packList = new JList(packLevels);
		JScrollPane packScrollPane = new JScrollPane(packList);
		packScrollPane.setPreferredSize(new Dimension(150,200));
		packScrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED), "Level Pack"));
		this.getContentPane().add(packScrollPane, BorderLayout.EAST);
	}
	
	/**
	 * Initialises the buttons used to modifiy and save a level pack.
	 */
	private void initButtons() {
		// Initialise control buttons
		JPanel buttonPanel = new JPanel();
		
		JButton addButton = new JButton("->");
		/**
		 * Add button action handler
		 */
		addButton.addActionListener(new ActionListener() {
			@Override
			/** Moves the selected item in the existing levels list to the level pack list */
			public void actionPerformed(ActionEvent e) {
				if (levelList.getSelectedIndex() >= 0 && levelList.getSelectedIndex() < loadedLevels.size()) {
					packLevels.addElement(loadedLevels.get(levelList.getSelectedIndex()));
				}
			}
		});
		buttonPanel.add(addButton);
		
		JButton removeButton = new JButton("<-");
		/**
		 * Remove button action handler
		 */
		removeButton.addActionListener(new ActionListener() {
			@Override
			/** Removes the selected item (if any) from the level pack list */
			public void actionPerformed(ActionEvent e) {
				if (packList.getSelectedIndex() >= 0 && packList.getSelectedIndex() < packLevels.size()) {
					packLevels.remove(packList.getSelectedIndex());
				}
			}
		});
		buttonPanel.add(removeButton);
		this.getContentPane().add(buttonPanel, BorderLayout.CENTER);
		
		JButton saveButton = new JButton("Save Level Pack");
		/**
		 * Save button action handler
		 */
		saveButton.addActionListener(new ActionListener()  {
			@Override
			/** Prompts the user for a filename, and attempts to save the level pack */
			public void actionPerformed(ActionEvent e) {
				if (packLevels.isEmpty()) {
					JOptionPane.showMessageDialog(LevelPackFrame.this, NO_LEVELS_SELECTED_MSG,
							ERROR_PANE_HEADER, JOptionPane.ERROR_MESSAGE);
					return;
				}
				
				try {
					String fileName = JOptionPane.showInputDialog(LevelPackFrame.this, SELECT_FILENAME_MSG, 
							"Save Level Pack", JOptionPane.QUESTION_MESSAGE);
					if (fileName != null && fileName != "") {
						File saveFile = new File("levels\\" + fileName + ".olp");
						// TODO: Ask the user if they want to overwrite
						if (!saveFile.exists()) { 
							saveFile.createNewFile();
							LevelPack exportLevelPack = new LevelPack();
							for(int i = 0; i < packLevels.getSize(); i++) {
								exportLevelPack.addLevel((String)packLevels.get(i));
							}
							if(exportLevelPack.exportLevelPack(saveFile)) {
								JOptionPane.showMessageDialog(null, LEVEL_PACK_SAVED_SUCCESFULLY_MSG
										, "Success!", JOptionPane.INFORMATION_MESSAGE);
							} else {
								throw new IOException();
							}
						} else {
							JOptionPane.showMessageDialog(null, LEVEL_PACK_FILE_EXISTS_MSG
									, ERROR_PANE_HEADER, JOptionPane.ERROR_MESSAGE);
						}
					}
				} catch (IOException err) {
					JOptionPane.showMessageDialog(null, ERROR_EXPORTING_MSG
							, ERROR_PANE_HEADER, JOptionPane.ERROR_MESSAGE);
					err.printStackTrace();
				}
			}
		});
		this.getContentPane().add(saveButton, BorderLayout.SOUTH);
	}
	
}
